﻿#light

namespace Twitter.Model

open System
open Utilities

type AuthedTwitterStore(username:string, password:string) =

    let requestBuilder = new RequestBuilder(username, password)
    do System.Net.ServicePointManager.Expect100Continue <- false // if this is not false then .NET will be default send a "100-Continue" header
                                                                 // twitter does not expect this header and therefore will fail, so we disable it
            
    interface ITwitterAuthStore with
        // statuses
        override this.GetStatus(id:int64) =
            let request = requestBuilder.BuildGetRequest("http://twitter.com/statuses/show/" + id.ToString() + ".xml")
            use response = request.GetResponse()
            TwitterXMLParser.ParseStatus(StreamToUTF8String(response.GetResponseStream()))
        
        override this.SetStatus(text:string, ?replyToStatus:int64) =
            let options = OptionBuilder([Some text; Int64Opt(replyToStatus)], ["status"; "in_reply_to_status_id"])

            let request = requestBuilder.BuildPostRequest("http://twitter.com/statuses/update.xml", options)
            use response = request.GetResponse()
            TwitterXMLParser.ParseStatus(StreamToUTF8String(response.GetResponseStream()))
        
        override this.DeleteStatus(id:int64) =
            let request = requestBuilder.BuildPostRequest("http://twitter.com/statuses/destroy/" + id.ToString() + ".xml")
            use response = request.GetResponse()
            ()
        
        // users
        override this.GetUser(name:string) =
            let request = requestBuilder.BuildGetRequest("http://twitter.com/users/show.xml", [("screen_name", name)])
            use response = request.GetResponse()
            TwitterXMLParser.ParseUser(StreamToUTF8String(response.GetResponseStream()))
            
        override this.SetUser(?name, ?email, ?url, ?location, ?description) =
            let options = OptionBuilder([name; email; url; location; description], ["name"; "email"; "url"; "location"; "description"])
            
            let request = requestBuilder.BuildPostRequest("http://twitter.com/account/update_profile.xml", options)
            use response = request.GetResponse()
            ()
        
        override this.GetFriends(?user:string, ?page:int) =
            let options = OptionBuilder([user; IntOpt(page)], ["screen_name"; "page"])
                                           
            let request = requestBuilder.BuildGetRequest("http://twitter.com/statuses/friends.xml", options)
            use response = request.GetResponse()
            TwitterXMLParser.ParseUserList(StreamToUTF8String(response.GetResponseStream()))
        
        override this.GetFollowers(?user:string, ?page:int) =
            let options = OptionBuilder([user; IntOpt(page)], ["screen_name"; "page"])
                                           
            let request = requestBuilder.BuildGetRequest("http://twitter.com/statuses/followers.xml", options)
            use response = request.GetResponse()
            TwitterXMLParser.ParseUserList(StreamToUTF8String(response.GetResponseStream()))
        
        // past statuses
        override this.GetArchive(?user:string, ?fromId:int64, ?toId:int64, ?page:int) =
            let options = OptionBuilder([user; Int64Opt(fromId); Int64Opt(toId); IntOpt(page)], ["screen_name"; "since_id"; "max_id"; "page"])
            
            let request = requestBuilder.BuildGetRequest("http://twitter.com/statuses/user_timeline.xml", options)
            use response = request.GetResponse()
            TwitterXMLParser.ParseStatusList(StreamToUTF8String(response.GetResponseStream()))
            
        override this.GetTimeline(?fromId:int64, ?toId:int64, ?count:int, ?page:int) =            
            let options = OptionBuilder([IntOpt(count); Int64Opt(fromId); Int64Opt(toId); IntOpt(page)], ["count"; "since_id"; "max_id"; "page"])
            
            let request = requestBuilder.BuildGetRequest("http://twitter.com/statuses/friends_timeline.xml", options)
            use response = request.GetResponse()
            TwitterXMLParser.ParseStatusList(StreamToUTF8String(response.GetResponseStream()))
            
        // direct messages
        override this.GetDirectMessages(?sinceId:int64, ?page:int) =
            let options = OptionBuilder([Int64Opt(sinceId); IntOpt(page)], ["since_id"; "page"])
            
            let request = requestBuilder.BuildGetRequest("http://twitter.com/direct_messages.xml", options)
            use response = request.GetResponse()
            TwitterXMLParser.ParseDirectMessageList(StreamToUTF8String(response.GetResponseStream()))
            
        override this.GetArchiveDirectMessages(?sinceId:int64, ?page:int) =
            let options = OptionBuilder([Int64Opt(sinceId); IntOpt(page)], ["since_id"; "page"])
            
            let request = requestBuilder.BuildGetRequest("http://twitter.com/direct_messages/sent.xml", options)
            use response = request.GetResponse()
            TwitterXMLParser.ParseDirectMessageList(StreamToUTF8String(response.GetResponseStream()))
            
        override this.SetDirectMessage(destination:string, text:string) =
            let request = requestBuilder.BuildPostRequest("http://twitter.com/direct_messages/new.xml", [("text", text); ("user", destination)])
            use response = request.GetResponse()
            TwitterXMLParser.ParseDirectMessage(StreamToUTF8String(response.GetResponseStream()))
            
        override this.DeleteDirectMessage(id:int64) =
            let request = requestBuilder.BuildPostRequest("http://twitter.com/direct_messages/destroy/" + id.ToString() + ".xml")
            use response = request.GetResponse()
            ()
        
        // friendships
        override this.CreateFriendship(name:string) =
            let request = requestBuilder.BuildPostRequest("http://twitter.com/friendships/create/" + name + ".xml")
            use response = request.GetResponse()
            ()
            
        override this.EndFriendship(name:string) =
            let request = requestBuilder.BuildPostRequest("http://twitter.com/friendships/destroy/" + name + ".xml")
            use response = request.GetResponse()
            ()
            
        override this.FriendshipExists(nameA:string, nameB:string) =
            let request = requestBuilder.BuildGetRequest("http://twitter.com/friendships/exists.xml", [("user_a", nameA); ("user_b", nameB)])
            use response = request.GetResponse()
            TwitterXMLParser.ParseBoolean(StreamToUTF8String(response.GetResponseStream()), "friends")
        
        // favorites
        override this.GetFavorites(?name:string, ?page:int) =
            let options = OptionBuilder([name; IntOpt(page)], ["id"; "page"])
            
            let request = requestBuilder.BuildGetRequest("http://twitter.com/favorites.xml", options)
            use response = request.GetResponse()
            TwitterXMLParser.ParseStatusList(StreamToUTF8String(response.GetResponseStream()))
            
        override this.CreateFavorite(id:int64) =
            let request = requestBuilder.BuildPostRequest("http://twitter.com/favorites/create/" + id.ToString() + ".xml")
            use response = request.GetResponse()
            ()
            
        override this.DestroyFavorite(id:int64) =
            let request = requestBuilder.BuildPostRequest("http://twitter.com/favorites/destroy/" + id.ToString() + ".xml")
            use response = request.GetResponse()
            ()
        
        // blocking
        override this.CreateBlock(name:string) =
            let request = requestBuilder.BuildPostRequest("http://twitter.com/blocks/create/" + name + ".xml")
            use response = request.GetResponse()
            ()
            
        override this.DestroyBlock(name:string) =
            let request = requestBuilder.BuildPostRequest("http://twitter.com/blocks/create/" + name + ".xml")
            use response = request.GetResponse()
            ()
        
        override this.TestAuth() =
            let request = requestBuilder.BuildGetRequest("http://twitter.com/account/verify_credentials.xml")
            
            try 
                use response = request.GetResponse()
                true
            with
                | :? Net.WebException as e -> false